﻿--status panel 
--durability code come from Tukui

  
--get the addon namespace
local addon, ns = ...
  
--get the config values
local LabelUI = ns.LabelUI
local cfg = ns.cfg

local noshow = LabelUI.noshow
local Kill = LabelUI.Kill
local point = LabelUI.point
local procsid
local InitConfigFrame = LabelUI.InitConfigFrame
local AddChatFunc = LabelUI.AddChatFunc

local classcolor
local playerclass
local playername
local iconsize
local barsize
local SaveVars
local Timer

local spiritspell = GetSpellInfo(27827)
local procs
local Slots = {}
local NumUsedlots = 0
local ProcCD = {}

local LoadConfig = function()
	Timer = LabelUI.Timer
	classcolor = cfg.classcolor 
	playerclass = cfg.playerclass
	playername = cfg.playername
	procsid = cfg.procsid
	SaveVars = LabelUI.SaveVars
	if cfg.frames.procs then
		iconsize = cfg.frames.procs.iconsize
	end
end

local function GetFreeSlot()
	local slot = #Slots
	for i = 0, slot do
		if not Slots[i] or not Slots[i].use then
			return i
		end
	end
	return slot + 1
end

local function ShowProc(self, duration)
	if self.slot == -1 then
		local slot = GetFreeSlot()
		if not Slots[slot] then
			Slots[slot] = CreateFrame("Frame", nil, procs)
			Slots[slot]:SetSize(iconsize, iconsize)
			Slots[slot].icon = Slots[slot]:CreateTexture(nil, "BORDER")
  			Slots[slot].icon:SetPoint('TOPLEFT',Slots[slot],'TOPLEFT', 2, -2)
  			Slots[slot].icon:SetPoint('BOTTOMRIGHT',Slots[slot],'BOTTOMRIGHT', -2, 2) 
  			Slots[slot].icon:SetTexCoord(0.1,0.9,0.1,0.9)
  			Slots[slot].iconBG = Slots[slot]:CreateTexture(nil, "BACKGROUND")
  			Slots[slot].iconBG:SetAllPoints(Slots[slot])
  			Slots[slot].iconBG:SetTexture(0, 0, 0, 1)
			Slots[slot].cd = CreateFrame("Cooldown", nil, Slots[slot])
  			Slots[slot].cd:SetAllPoints(Slots[slot].icon)
			Slots[slot]:Hide()
		end
		Slots[slot].icon:SetTexture(self.texture)
		Slots[slot].iconBG:SetTexture(0, 1, 0, 1)
		Slots[slot].use = self
		Slots[slot]:SetPoint('LEFT',procs ,'TOPLEFT', (iconsize + 2) * slot, 0) 
		Slots[slot].cd:SetCooldown(GetTime(), duration)
		Slots[slot].cd:Show()
		Slots[slot].intcd = self.cd - duration
		NumUsedlots = NumUsedlots + 1
		procs:SetWidth(iconsize * NumUsedlots + 2 * (NumUsedlots - 1))
		self.slot = slot
		Slots[slot]:Show()
	else
		Slots[self.slot].iconBG:SetTexture(0, 1, 0, 1)
		Slots[self.slot].cd:SetCooldown(GetTime(), duration)
		Slots[self.slot].cd:Show()
		Slots[self.slot].intcd = self.cd - duration
		if Slots[self.slot].timerid then
			Timer:Stop(Slots[self.slot].timerid)
			Slots[self.slot].timerid = false
		end
		Slots[self.slot]:Show()
	end
end


local function HideProc(self)
	if self.slot ~= -1 then
		Slots[self.slot]:Hide()
		Slots[self.slot].timerid = false
		Slots[self.slot].use = false
		NumUsedlots = NumUsedlots - 1
		self.slot = -1
	end
end

local function UpdateProc(self, duration, expires)
	if self.slot ~= -1 then
		Slots[self.slot].cd:SetCooldown(expires - duration, duration)
	end
end

local function ProcStartCD(self)
	if self.slot ~= -1 then
		Slots[self.slot].iconBG:SetTexture(0, 0, 0, 1)
		Slots[self.slot].cd:SetCooldown(GetTime(), Slots[self.slot].intcd)
		Slots[self.slot].cd:Show()
		Slots[self.slot].timerid = Timer:Start(Slots[self.slot].intcd, function() self:Finish() end)
	end
end

local function ProcFinished(self)
	self:Hide()
end

local function UpdateCDValue(self, type)
	local count	= SaveVars:Get("procs|db|"..self.id.."|count", 1)
	local oldtime = SaveVars:Get("procs|db|"..self.id.."|time", 0)
	if type == "start" then
		ProcCD[self.id] = GetTime()
		self.cd = oldtime / count
	elseif type == "stop" and ProcCD[self.id] then
		if count < 20 then
			SaveVars:Set("procs|db|"..self.id.."|time", oldtime + (GetTime() - ProcCD[self.id]))
			if oldtime ~= 0 then
				SaveVars:Set("procs|db|"..self.id.."|count", count + 1)
			end
		else
			local updatetime = oldtime - oldtime / 20
			SaveVars:Set("procs|db|"..self.id.."|time", updatetime + (GetTime() - ProcCD[self.id]))
		end
	end
end

local function AddSpell(spellid, cd)
	local spell = {}
	spell.Show = ShowProc
	spell.Hide = HideProc
	spell.Update = UpdateProc
	spell.StartCD = ProcStartCD
	spell.Finish = ProcFinished
	spell.id = spellid
	if cd == "calc" then 
		spell.cd = SaveVars:Get("procs|db|"..spellid.."|time", 0) / SaveVars:Get("procs|db|"..spellid.."|count", 1)
		spell.UpdateCD = UpdateCDValue
	else
		spell.cd = cd
		spell.UpdateCD = noshow
	end
	spell.name, _, spell.texture = GetSpellInfo(spellid)
	spell.slot = -1
	return spell
end


local function ProcUpdate(spell)
	local duration, expires = select(6, UnitAura("player", spell.name))
	if duration then
		spell:Update(duration, expires)
	end
end

local function ProcStart(spell)
	local duration = select(6, UnitAura("player", spell.name))
	if duration then
		spell:UpdateCD("stop")
		spell:Show(duration)
	end
end

local function ProcEnd(spell)
	spell:UpdateCD("start")
	spell:StartCD()
end

local function Event(self, event, ...)
	if event == "PLAYER_CONTROL_LOST" or event == "PLAYER_REGEN_ENABLED" then
		ProcCD = {}
	else
		local eventtype = select(2, ...)
    	local unitname = select(9, ...)
		local spellid = select(12, ...)
    	local spelltype = select(15, ...)
 		if eventtype == "SPELL_AURA_APPLIED" and playername == unitname and spelltype == "BUFF" then
			if procs.spells[spellid] then
				ProcStart(procs.spells[spellid])
			end
		elseif eventtype == "SPELL_AURA_REMOVED" and playername == unitname and spelltype == "BUFF" then
			if procs.spells[spellid] then
				ProcEnd(procs.spells[spellid])
			end
		elseif eventtype == "SPELL_AURA_REFRESH" and playername == unitname and spelltype == "BUFF" then
			if procs.spells[spellid] then
				ProcUpdate(procs.spells[spellid])
			end
		elseif eventtype == "UNIT_DIED" and (UnitIsDeadOrGhost("player") == 1 or UnitAura("player", spiritspell) == spiritspell) then
			ProcCD = {}
		end
	end
end

local function CreateBar()
	if not procs and iconsize then
		procs = CreateFrame("Frame", "LUI_Procs", UIParent)
		procs:SetPoint(cfg.frames.procs.pos.a1,point(cfg.frames.procs.pos.af),cfg.frames.procs.pos.a2, cfg.frames.procs.pos.x, cfg.frames.procs.pos.y)
		procs:SetHeight(iconsize)
		procs:SetWidth(0)
		procs:SetFrameStrata("BACKGROUND")
		procs.spells = {}
		for id, cd in pairs(procsid) do
			procs.spells[id] = AddSpell(id, cd)
		end
		procs:RegisterEvent("COMBAT_LOG_EVENT_UNFILTERED")
		procs:RegisterEvent("PLAYER_CONTROL_LOST")
		procs:RegisterEvent("PLAYER_REGEN_ENABLED")
		procs:SetScript("OnEvent", Event)
		procs:Show()
	elseif iconsize then
		procs:Show()	
	end
end

local function CreateConfigChanger()
	local curent
	local all = {
		[1] = "enable",
		[2] = "disable",	
	}
	if SaveVars:Get("procs|show", false) then
		curent = all[1]
	else
		curent = all[2]
	end
	local elementtable = {
		[1] = {
			type = "label",
			point = { a1 = "TOPRIGHT", a2 = "BOTTOM", af = "self.title", x = 0, y = 0 }, 
			point2 = { a1 = "TOPLEFT", a2 = "BOTTOMLEFT", af = "self.title", x = 0, y = 0 }, 	
			height = 60,
			font = "Interface\\AddOns\\LabelUI\\media\\Aquarion.otf",
			size = 14,
			justifyh = "LEFT",
			text = "Procs:",
			name = "procs",
		},
		[2] = {
			type = "dropdown",
			point = { a1 = "LEFT", a2 = "RIGHT", af = "self.named['procs']", x = 0, y = 0 }, 
			point2 = { a1 = "RIGHT", a2 = "RIGHT", af = "self.title", x = 0, y = 0 }, 	
			all = all,
			curent = curent,
			font = "Interface\\AddOns\\LabelUI\\media\\Aquarion.otf",
			size = 13,
			name = "procsdropdown",
		},
	}
	local func = function(self)
	  	if self.named['procsdropdown'].text:GetText() ~= curent then
	  	 	if self.named['procsdropdown'].text:GetText() == all[1] then
				SaveVars:Set("procs|show", true)	
				CreateBar()
			else
				SaveVars:Set("procs|show", false)
				if procs then
					procs:Hide()
				end 	
			end
      	end	
	end
	InitConfigFrame(elementtable, 250, 250, func)
end

local function Init()
	LoadConfig()
	if SaveVars:Get("procs|show", false) then
		CreateBar()
	end
	AddChatFunc("Procs", CreateConfigChanger)
end

LabelUI:AddInit(Init, "Procs")

